/*
-----------------------------------------------------------------------------
This source file is part of DIVA
The project of Engineering Lab, dept. of CSIE, NTNU.

Copyright (c) 2000-2006 The Software Engineering Lab, dept. of CSIE, NTNU.
-----------------------------------------------------------------------------
Filename:    DIVA_FrameListener.cpp
Description: The file implements all the method and initialise all the variables
             defined in the DIVA_FrameListener.cpp.
-----------------------------------------------------------------------------
*/

#include "DIVA_FrameListener.h"
#include "DIVA_InputManager.h"
#include "DIVA_RenderData.h"
#include "DIVA_Manager.h"
#include "QDivaAppController.h"
#include "MappingEngine.h"
#include "DragVMToDestination.h"
#include "animationCenter.h"
#include "InterpolationCenter.h"
//FORTEST
#include "ExplorBotLibrary.h"
#include "LayoutInterpolation.h"

#include <xTitanClient/xTitan.hpp>

//extern HINSTANCE _hInst ;  // this instance is defined in DIVA_MAIN
//extern HWND _hWnd ;        // this instance is defined in DIVA_Application
//
//BOOL CALLBACK MakeVMProc(HWND,UINT,WPARAM,LPARAM);
//BOOL CALLBACK AnimationProc(HWND,UINT,WPARAM,LPARAM);

// Constructor
DIVA_FrameListener::DIVA_FrameListener(Ogre::SceneManager* mgr, Ogre::RenderWindow* win, Ogre::Camera* cam){
	
	mSceneMgr = mgr;
    mCamera = cam;
    mWindow = win;
    DIVA_InputManager::getSingletonPtr()->initialise( mWindow );
	_firsttime = true ;
	str = "Examples/MorningSkyBox";

	//// Create a user input -- MyExampleInput
	//MyExampleInput::getInstance()->init(mgr, mCamera);
	//mInput = MyExampleInput::getInstance();//new MyExampleInput( mgr , mCamera );
	//// Add this input system into the inputmanager
	//DIVA_InputManager::getSingletonPtr()->addKeyListener(mInput,mInput->getKeyName());
	//DIVA_InputManager::getSingletonPtr()->addMouseListener(mInput,mInput->getMouseName());

	mSkipCount = 0;
    mUpdateFreq = 50;
	mTranslateVector = Ogre::Vector3::ZERO;
	mCenterPosition = Ogre::Vector3::ZERO;
	
	_isTurnedOn = true;
}

// Destructor
DIVA_FrameListener::~DIVA_FrameListener(){
	
}


int eventCount = 0;
int Count = 0;
int testUpdateCount = 0;
int testTotalKeyPressedCount = 0;
bool g_visible = true ;
bool justturn_visible = false ;

// Override frameStarted event to process that (don't care about frameEnded)
bool DIVA_FrameListener::frameStarted(const Ogre::FrameEvent& evt){
	
	DIVA_Manager::getInstance()->lock();  // to prevent the races between WOP server thread
	if(!_isTurnedOn){ 
		DIVA_Manager::getInstance()->release();
		return true; // skip below routine to avoid potential deadlock caused inside WOP_Entry::setVM()
	}

	if (mWindow->isVisible() == false && g_visible == true) {		   
			g_visible = false ;
			//MyExampleInput::getInstance()->setcurrentMouseButtonID(OIS::MB_Button3);
	}

	if (mWindow->isVisible() == true && g_visible == false) {
			// this is to fix a bug:
		    // when the window is minimized and then maximized again
		    // the currentMoiseButtonID is still MB_Left 
		    // So the camera is rotated but mouse cursor is not inside the window
		    g_visible = true ;
			justturn_visible = true ; // justturn_visible is a global variable accessed by MyExampleInput.cpp
														  // go to MyExampleInput::MousePressed() to check how
	}

    if(mWindow->isClosed())
       return false;

    if (mSkipCount++ >= mUpdateFreq){
        mSkipCount = 0;
    }

	DIVA_RenderData* data = DIVA_RenderData::getSingletonPtr();
	if(data->ifUpdated()){
		float shift = data->mAvgFrameTime * MOVESPEED;		

        mTranslateVector.x += data->ifMoveLeft() ? -shift : 0;
        mTranslateVector.x += data->ifMoveRight() ? shift : 0;
        mTranslateVector.z += data->ifMoveFwd() ? -shift : 0;
        mTranslateVector.z += data->ifMoveBck() ? shift : 0;
		mTranslateVector.y += data->ifMoveUp() ? shift: 0 ;
		mTranslateVector.y += data->ifMoveDown() ? -shift:0 ;

		//////////////////////////////////////////////////////////////////////////
		// added by Luke for testing zoom in / zoom out when mouse wheel rotating.		
		mTranslateVector.z -= DIVA_Application::getInstance()->getController()->zoomLevel();
		//////////////////////////////////////////////////////////////////////////

		if (data->ifRollRight()) {
	 		float speed = data->mAvgFrameTime * 20;
			data->mRotZ = speed ;
		}
		if (data->ifRollLeft()) {
	 		float speed = data->mAvgFrameTime * 20;
			data->mRotZ = -speed ;
		}

		//mCamera->yaw(Ogre::Angle(data->mRotX));
        //mCamera->pitch(Ogre::Angle(data->mRotY));
		//mCamera->roll(Ogre::Angle(data->mRotZ));

		Ogre::Real radius = mCamera->getPosition().distance(mCenterPosition);
		Ogre::Real z = 0.0;
		if (data->mRotX!=0.0){
			z = radius - Ogre::Math::Sqrt((radius*radius)- (data->mRotX*data->mRotX));
		} else if ( data->mRotY!=0.0){
			z = radius - Ogre::Math::Sqrt((radius*radius)- (data->mRotY*data->mRotY));
		}
		// if user rotated carema, set carema position and rotate camera to look at center of render window
		mCamera->moveRelative(Ogre::Vector3(data->mRotX,data->mRotY,-z));
		if ( mTranslateVector.isZeroLength()){
			mCamera->lookAt(Ogre::Vector3(mCenterPosition.x,mCenterPosition.y,mCenterPosition.z));
		}
		
		// if user move carema up down left right, set new position to center of render window
		Ogre::Vector3 oldCamermaPosition = mCamera->getPosition();
		mCamera->moveRelative(mTranslateVector);
		if ( mTranslateVector.z == 0.0){
			mCenterPosition += mCamera->getPosition() - oldCamermaPosition;
		}

		
        data->mRotX = 0;
        data->mRotY = 0;
		data->mRotZ = 0 ;
        mTranslateVector = Ogre::Vector3::ZERO;

    } 
	if (data->ifOrigin()) {
		// Position it at 500 in Z direction
	    mCamera->setPosition(Ogre::Vector3(0,0,500));
	
		// Look back along -Z
		mCamera->lookAt(Ogre::Vector3(0,0,-300));
		data->origin(false);
		mCenterPosition = Ogre::Vector3::ZERO;
	}

	/// update all the vm state
	// DIVA_Manager::getInstance()->update_all_VM_List(); // add at 070605
	MappingEngine::getInstance()->doLayoutForNewVM() ;	DIVA_Manager::getInstance()->triggerAllVMAnimation(evt); // pass the frameEvent to all VMAnimations 2007/10/08 by ypc
	//
	//if (!MappingEngine::getInstance()->is_mappingwd_displayed()) {
	//	// when a mapping window is displayed, we do not want to 
	//	// mess up with the following
	//	MappingEngine::getInstance()->map_one_wop_to_vm();	 // if there are new wops which are newly added to DIVA, assign new VM to these wops 
	//	
	//}
	
	///add by James 為了做出移動的效果
	DragVMToDestination::getInstance()->move();
	//added by ad1339 2009/5/2x 加入動畫效果
	//add by hyt 2009/12/14
	/*先拿掉 2012/12/18
	if(InterpolationCenter::getInstance()->getStatus()){
		// if animation is set, we are going to render the interpolated frame 
		InterpolationCenter::getInstance()->render(evt.timeSinceLastFrame);
	}
	else{
		animationCenter::getInstance()->animate(evt.timeSinceLastFrame);
	}
	*/
	ExplorBotLibrary::getInstance()->doExplor();
	// 20121230 加入動畫效果
	LayoutInterpolation::getInstance()->doInterpolation(evt.timeSinceLastFrame);

	DIVA_Manager::getInstance()->release();
	return true;
}

// frameEnded method -
bool DIVA_FrameListener::frameEnded(const Ogre::FrameEvent& evt){
    return true;
}

void DIVA_FrameListener::switchFrameListener( bool turnedOn ){
	this->_isTurnedOn = turnedOn;
	ExplorBotLibrary::getInstance()->setDo(true); //20130129 add
}

bool DIVA_FrameListener::frameRenderingQueued( const Ogre::FrameEvent& evt )
{
	return true;
}
